﻿using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Security.Cryptography;

namespace Steganograf
{
    public class Crypto
    {
        public static byte[] GetSha512Key(string pPassword)
        {
            SHA512 sha512 = new SHA512CryptoServiceProvider();
            return sha512.ComputeHash(new UTF8Encoding().GetBytes(pPassword));
        }

        public static string EncryptAes(string pPlainMessage, string pPassword)
        {
            return EncryptDecryptAes(pPlainMessage, pPassword, true);
        }

        public static string DecryptAes(string pEncryptedMessage, string pPassword)
        {
            return EncryptDecryptAes(pEncryptedMessage, pPassword, false);
        }

        private static string EncryptDecryptAes(string pMessage, string pPassword, bool pEncrypt)
        {
            byte[] IV = Encoding.ASCII.GetBytes(m_InitVector);
            byte[] salt = Encoding.ASCII.GetBytes(m_SaltValue);
            byte[] message = null;
            if (pEncrypt)
            {
                message = Encoding.UTF8.GetBytes(pMessage);
            }
            else
            {
                message = Convert.FromBase64String(pMessage);
            }
            
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(pPassword, salt, m_HashAlgorithm, m_PasswordIterations);
            byte[] key = pdb.GetBytes(m_KeySize / 8);

            AesManaged aes = new AesManaged();
            aes.Mode = CipherMode.CBC;
            ICryptoTransform cryptor = null;
            byte[] returnMessage = null;
            if(pEncrypt)
            {
                cryptor = aes.CreateEncryptor(key, IV);
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptor, CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(message, 0, message.Length);
                        cryptoStream.FlushFinalBlock();
                        returnMessage = memoryStream.ToArray();
                    }
                }

                return Convert.ToBase64String(returnMessage);
            }
            else
            {
                cryptor = aes.CreateDecryptor(key, IV);
                int decryptedByteCount = 0;
                using (MemoryStream memoryStream = new MemoryStream(message))
                {
                    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptor, CryptoStreamMode.Read))
                    {
                        returnMessage = new byte[message.Length];
                        decryptedByteCount = cryptoStream.Read(returnMessage, 0, returnMessage.Length);
                    }
                }

                return Encoding.UTF8.GetString(returnMessage, 0, decryptedByteCount);
            }
        }

        private static string m_InitVector = "@Cl9hRWiczqpSAGX";
        private static string m_SaltValue = "saltvalue";
        private static string m_HashAlgorithm = "SHA512";
        private static int m_PasswordIterations = 3;
        private static int m_KeySize = 256;
    }
}
